#include "include.h"
#include "func.h"
#include "func_bt.h"

#define MAX_DIG_VAL             32767
#define AEC_DIG_P0DB            (MAX_DIG_VAL * 1.000000)
#define AEC_DIG_P1DB            (MAX_DIG_VAL * 1.122018)
#define AEC_DIG_P2DB            (MAX_DIG_VAL * 1.258925)
#define AEC_DIG_P3DB            (MAX_DIG_VAL * 1.412538)
#define AEC_DIG_P4DB            (MAX_DIG_VAL * 1.584893)
#define AEC_DIG_P5DB            (MAX_DIG_VAL * 1.778279)
#define AEC_DIG_P6DB            (MAX_DIG_VAL * 1.995262)
#define AEC_DIG_P7DB            (MAX_DIG_VAL * 2.238721)
#define AEC_DIG_P8DB            (MAX_DIG_VAL * 2.511886)
#define AEC_DIG_P9DB            (MAX_DIG_VAL * 2.818383)
#define AEC_DIG_P10DB           (MAX_DIG_VAL * 3.162278)
#define AEC_DIG_P11DB           (MAX_DIG_VAL * 3.548134)
#define AEC_DIG_P12DB           (MAX_DIG_VAL * 3.981072)
#define AEC_DIG_P13DB           (MAX_DIG_VAL * 4.466836)
#define AEC_DIG_P14DB           (MAX_DIG_VAL * 5.011872)
#define AEC_DIG_P15DB           (MAX_DIG_VAL * 5.623413)

typedef struct {
    u8 aec_en;
    u8 wnr_en;
    u8 alc_en;
    u8 mic_eq_en;

    u8 aec_echo_level;
    u8 aec_far_offset;
    //降噪
    u16 noise_threshoid;

    u8 alc_fade_in_step;
    u8 alc_fade_out_step;
    u8 alc_fade_in_delay;
    u8 alc_fade_out_delay;
    s32 alc_far_voice_thr;
    u16 far_noise_threshoid;    //远端降噪阈值
    u8 far_nr_en;
    u8 ans_radio;
} bt_voice_cfg_t;

static bt_voice_cfg_t bt_voice_cfg AT(.sco_data);
int sfunc_bt_call_flag;
void bt_voice_init(bt_voice_cfg_t *p);
void bt_voice_exit(void);
void bt_sco_rec_exit(void);

AT(.bt_voice.gain.tbl)
const int mic_gain_tbl[15] = {
    AEC_DIG_P1DB,
    AEC_DIG_P2DB,
    AEC_DIG_P3DB,
    AEC_DIG_P4DB,
    AEC_DIG_P5DB,
    AEC_DIG_P6DB,
    AEC_DIG_P7DB,
    AEC_DIG_P8DB,
    AEC_DIG_P9DB,
    AEC_DIG_P10DB,
    AEC_DIG_P11DB,
    AEC_DIG_P12DB,
    AEC_DIG_P13DB,
    AEC_DIG_P14DB,
    AEC_DIG_P15DB,
};

////库调用，设置MIC的增益（算法之后）
AT(.bt_voice.aec)
int sco_set_mic_gain_after_aec(void)
{
    if (xcfg_cb.mic_post_gain) {
        return mic_gain_tbl[xcfg_cb.mic_post_gain - 1];
    }
    return 0;
}

#if BT_SCO_DBG_EN
void sdadc_set_digital_gain(u8 gain);
void sco_audio_set_param(u8 type, u16 value)
{
    //printf("set param[%d]:%d\n", type, value);
    if (type == AEC_PARAM_NOISE) {
        xcfg_cb.bt_noise_threshoid = value;
        bt_voice_cfg.noise_threshoid = value;
    } else if (type == AEC_PARAM_LEVEL) {
        xcfg_cb.bt_echo_level = value;
        bt_voice_cfg.aec_echo_level = value;
    } else if (type == AEC_PARAM_OFFSET) {
        xcfg_cb.bt_far_offset = value;
        bt_voice_cfg.aec_far_offset = value;
    } else if (type == AEC_PARAM_MIC_ANL_GAIN) {
        xcfg_cb.bt_anl_gain = value;
        set_mic_analog_gain(value, CH_MIC_PF2);
    } else if (type == AEC_PARAM_MIC_DIG_GAIN) {
        xcfg_cb.bt_dig_gain = value;
        sdadc_set_digital_gain(value & 0x3f);
    } else if (type == AEC_PARAM_MIC_POST_GAIN) {
        xcfg_cb.mic_post_gain = value & 0x0f;
    }
}
#endif // BT_SCO_DBG_EN

#if FUNC_BT_EN
void sco_audio_init(void)
{
    memset(&bt_voice_cfg, 0, sizeof(bt_voice_cfg_t));
    bt_voice_cfg.noise_threshoid = BT_NOISE_THRESHOID;
    bt_voice_cfg.ans_radio = xcfg_cb.bt_sco_ans_radio;
#if BT_AEC_EN
    if (xcfg_cb.bt_aec_en) {
        xcfg_cb.bt_alc_en = 0;
        bt_voice_cfg.aec_en = 1;
        bt_voice_cfg.aec_echo_level = BT_ECHO_LEVEL;
        bt_voice_cfg.aec_far_offset = BT_FAR_OFFSET;
    }
#endif

#if BT_ALC_EN
    if (xcfg_cb.bt_alc_en) {
        bt_voice_cfg.alc_en = 1;
        bt_voice_cfg.alc_fade_in_delay = BT_ALC_FADE_IN_DELAY;
        bt_voice_cfg.alc_fade_in_step = BT_ALC_FADE_IN_STEP;
        bt_voice_cfg.alc_fade_out_delay = BT_ALC_FADE_OUT_DELAY;
        bt_voice_cfg.alc_fade_out_step = BT_ALC_FADE_OUT_STEP;
        bt_voice_cfg.alc_far_voice_thr = BT_ALC_VOICE_THR;
    }
#endif

#if BT_HFP_REC_EN
    func_bt_sco_rec_init();
#endif
    if (mic_set_eq_by_res(&RES_BUF_EQ_BT_MIC_EQ, &RES_LEN_EQ_BT_MIC_EQ)) {
        bt_voice_cfg.mic_eq_en = 1;
    }
#if SYS_KARAOK_EN
    bsp_karaok_exit(AUDIO_PATH_KARAOK);
    sys_cb.hfp_karaok_en = BT_HFP_CALL_KARAOK_EN;       //通话是否支持KARAOK
    plugin_hfp_karaok_configure();
    if (sys_cb.hfp_karaok_en) {
        bsp_karaok_init(AUDIO_PATH_BTMIC, FUNC_BT);
        kara_sco_start();
    } else
#endif
    {
        bt_voice_init(&bt_voice_cfg);
		bt_sco_remove_pkt_set_cnt(0);
        dac_set_anl_offset(1);
        audio_path_init(AUDIO_PATH_BTMIC);
        audio_path_start(AUDIO_PATH_BTMIC);
        bsp_change_volume(bsp_bt_get_hfp_vol(sys_cb.hfp_vol));
        dac_fade_in();
    }
}

void sco_audio_exit(void)
{
#if BT_HFP_REC_EN
    sfunc_record_stop();
    bt_sco_rec_exit();
#endif
#if SYS_KARAOK_EN
    if (sys_cb.hfp_karaok_en) {
        kara_sco_stop();
        bsp_karaok_exit(AUDIO_PATH_BTMIC);
        sys_cb.hfp_karaok_en = 0;
    } else
#endif
    {
        dac_fade_out();
        dac_aubuf_clr();
        audio_path_exit(AUDIO_PATH_BTMIC);
        bt_voice_exit();
        dac_set_anl_offset(0);
        bsp_change_volume(sys_cb.vol);
    }

#if SYS_KARAOK_EN
    bsp_karaok_init(AUDIO_PATH_KARAOK, FUNC_BT);
#endif

#if BT_REC_EN && BT_HFP_REC_EN
    bt_music_rec_init();
#endif
}
AT(.text.func.bt)
void bt_call_check_light_status(void)
{
	if(bsp_get_light_mode()!=0)
	{
		sys_cb.light_idle_cnt++;
		printf("light time out cnt:%d\n",sys_cb.light_idle_cnt);
		if(sys_cb.light_idle_cnt>=60*60)
		{
			bsp_set_light_off();
			sys_cb.light_idle_cnt=0;
		}
	}
}

static void sfunc_bt_call_process(void)
{
    func_process();
    func_bt_sub_process();
    if(sco_is_connected() && (sfunc_bt_call_flag == 1)){
        sfunc_bt_call_flag = 2;
        bsp_change_volume(bsp_bt_get_hfp_vol(sys_cb.hfp_vol));
        dac_fade_in();
    }
}

static void sfunc_bt_call_enter(void)
{
    sfunc_bt_call_flag = 1;
	amp_speaker_unmute();
}

static void sfunc_bt_call_exit(void)
{
	bsp_set_led_mode(LED_BT_CALL_REJECT);
    bsp_change_volume(sys_cb.vol);
    sfunc_bt_call_flag = 0;
#if SYS_KARAOK_EN && BT_HFP_CALL_PRIVATE_FORCE_EN
    bsp_karaok_init(AUDIO_PATH_KARAOK, FUNC_BT);
#endif // SYS_KARAOK_EN
	if(!sys_cb.key_hangup)
	{
		bsp_set_led_mode(LED_POWER_ON);
		sys_cb.key_hangup=0;
	}

}

AT(.text.func.bt)
void sfunc_bt_call(void)
{
    printf("%s\n", __func__);

    sfunc_bt_call_enter();
#if DAC_DNR_EN
    u8 sta = dac_dnr_get_sta();
    dac_dnr_set_sta(0);
#endif

    while ((f_bt.disp_status >= BT_STA_OUTGOING) && (func_cb.sta == FUNC_BT)) {
        sfunc_bt_call_process();
        sfunc_bt_call_message(msg_dequeue());
        func_bt_display();
    }

#if DAC_DNR_EN
    dac_dnr_set_sta(sta);
#endif
    sfunc_bt_call_exit();
}
#else

void sco_audio_init(void){}
void sco_audio_exit(void){}

#endif //FUNC_BT_EN
